package com.lzwork.gpt.utility.batchjob.inner.loader;

import java.io.File;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.function.Consumer;

import com.lzwork.gpt.utility.batchjob.JobOption;
import com.lzwork.gpt.utility.batchjob.inner.InnerJob;
import com.lzwork.gpt.utility.batchjob.inner.InnerJob.SourceLoader;
import com.lzwork.utility.TimeTicker;
import com.lzwork.utility.collection.CollUtility;
import com.lzwork.utility.file.FileUtility;
import com.lzwork.utility.file.csv.CsvFormReader;
import com.lzwork.utility.file.csv.CsvFormReader.CsvLoadSetting;
import com.lzwork.utility.file.form.FormLine;
import com.lzwork.utility.file.form.FormPage;
import com.lzwork.utility.file.form.LineData;
import com.lzwork.utility.officeparser.ExcelReader;
import com.lzwork.utility.officeparser.ExcelReader.ColumnIndex;
import com.lzwork.utility.officeparser.ExcelReader.Page;
import com.lzwork.utility.officeparser.ExcelReaderEv;

import lombok.Getter;

/**
 * @author LiZheng
 * @date 2024年9月10日 10:20:20
 */

public class FormLoader implements SourceLoader
{
	@Getter
	protected List<String> fullInputFields = new ArrayList<>();

	@Override
	public List<LineData> loadSource(File input, JobOption option, Consumer<String> logger) throws InterruptedException
	{
		List<LineData> allLines = new ArrayList<>();
		List<? extends FormPage> pages;
		TimeTicker ticker = new TimeTicker();

		String ext = FileUtility.getFileExt(input);

		switch (ext)
		{
		case ".xls":
			pages = ExcelReader.read(input);
			break;
		case ".csv":
			pages = CollUtility
					.arrayToList(CsvFormReader.readFromFile(input, new CsvLoadSetting(null, true, option.charset())));
			break;
		default:
			pages = ExcelReaderEv.readData(input);
			break;
		}

		if (logger != null)
			logger.accept("Load source done. Cost: " + ticker.tickS());

		int all = 0;
		int skip = 0;

		Set<String> fieldFilters = new HashSet<>();
		if (CollUtility.hasData(option.fieldFilter()))
		{
			fieldFilters.addAll(option.requireFields());
			fieldFilters.addAll(option.fieldFilter());
		}

		for (FormPage p : pages)
		{
			InnerJob.jobBreakCheck();

			if (p.getRows().isEmpty())
				continue;

			ColumnIndex fields;

			if (p instanceof Page)
				fields = ((Page) p).getFieldIndex();
			else
				fields = new ColumnIndex(p.getColumnMap());

			List<String> missing = fields.checkMissingFields(option.requireFields());

			if (!missing.isEmpty())
			{
				if (logger != null)
					logger.accept("Skip page [" + p.getName() + "] for missing column: " + missing);
				continue;
			}

			fullInputFields.addAll(fields.allFields());
			all += p.getRows().size();

			for (FormLine line : p.getRows())
			{
				if (line.hasData())
				{
					LineData ld = LineData.copy(line, fieldFilters);
					allLines.add(ld);
				} else
					skip++;
			}
		}

		pages.clear();

		if (logger != null)
		{
			logger.accept("Total " + allLines.size() + "/" + all + " lines loaded. Skipped " + skip + " empty lines.");
		}

		return allLines;
	}

}
